#pragma once

#include<functional>
#include<memory>
#include"Timestamp.h"
#include"noncopyable.h"

//当前头文件中只用到了类型的声明，
//并没有用到具体类型或者方法，所以这里头文件中只需要写这些类型的前置声明就行，到时候只在源文件中给出头文件，反正最后都会被生成so库
class Eventloop;
//class Timestamp;这个在handleEvent中使用了对象，所以不像Eventloop *loop一样是个指针确定四个字节
//这个对象不确定大小，所以得包含它的头文件，不能只声明


//channel理解为通道，封装了sockfd和其感兴趣的event，如EPLLIN等，还绑定了poller返回的具体事件
class Channel:noncopyable
{
    public:
        using EventCallback=std::function<void()>;//事件的回调
        using ReadEventCallback=std::function<void(Timestamp)>;//只读事件的回调

        Channel(Eventloop *loop,int fd);
        ~Channel();

        void handleEvent(Timestamp receiveTime);
       

        //设置回调函数操作
        void setReadCallback(ReadEventCallback cb){readCallback_=std::move(cb);}
        void setWriteCallback(EventCallback cb){writeCallback_=std::move(cb);}
        void setCloseCallback(EventCallback cb){closeCallback_=std::move(cb);}
        void setErrorCallback(EventCallback cb){errorCallback_=std::move(cb);}

        //防止当channel被手动remove掉，channel还在执行回调操作，使用这个来进行监听
        void tie(const std::shared_ptr<void>&);
        int fd() const {return fd_;}
        int events(){return events_;}
        
        //为什么设置这个接口？因为这是给poller设计的，channel本身不能监听自己的事件，一定是poller监听了通过这个接口设置给它
        int set_revents(int revt) {revents_=revt;}
        //当前这个channel有没有注册感兴趣的事件，为啥要有这么个接口呢？？
        //bool isNoneEvent() const {return events_==kNoneEvent;}

        //设置、修改、去除感兴趣的事件
        void enableReading(){events_ |= kReadEvent;update();}
        void disableReading(){events_ &=~ kReadEvent;update();}
        void enableWriting(){events_ |= kWriteEvent;update();}
        void disableWriting(){events_&=~ kWriteEvent;update();}
        void disableAll(){events_ =kNoneEvent;update();}

        //返回fd当前的事件状态
        bool isNoneEvent() const {return events_==kNoneEvent;}
        bool isWriting() const {return events_&kWriteEvent;}
        bool isReading() const {return events_&kReadEvent;}

        int index(){return index_;}
        void set_index(int idx){index_=idx;}

        Eventloop* ownerLoop(){return loop_;}
        void remove();

    private:
        void update();
        void handleEventWithGuard(Timestamp receiveTime);
        //下面这三个表示的是fd的状态，不感兴趣、对读事件感兴趣、对写事件感兴趣
        static const int kNoneEvent;
        static const int kReadEvent;
        static const int kWriteEvent;

        Eventloop *loop_;//表示事件循环
        const int fd_;//fd,poller监听的对象
        int events_;//注册fd感兴趣的事件
        int revents_;//poller返回的具体发生的事件
        int index_;//在Poller中的状态标记，kNew(-1),kAdded(1)：已添加到poller。kDeleted(2)已从poller删除,优化 epoll_ctl 调用（避免重复 ADD/DEL）跟踪 Channel 在 Poller 中的状态
        std::weak_ptr<void> tie_;
        bool tied_;

        //因为channel里面能获知fd最终发生的具体的事件revents，所以它负责具体事件的回调操作
        ReadEventCallback readCallback_;
        EventCallback writeCallback_;
        EventCallback closeCallback_;
        EventCallback errorCallback_;

};